package sivan.test;

import org.junit.Test;
import org.springframework.cglib.beans.BeanCopier;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import sivan.annotation.BaseConfig;
import sivan.service.UserService;
import sun.misc.ProxyGenerator;

import java.io.FileOutputStream;
import java.lang.reflect.Proxy;

/**
 * BeanCopier类拷贝对象
 */
public class BeanCopierDemo {

    @Test
    public void main() {
        ASMDemo.Test test = new ASMDemo.Test();
        test.setId(1);
        test.setName("adasda");

        ASMDemo.Test test1 = new ASMDemo.Test();
        BeanCopier copier = BeanCopier.create(test.getClass(), test.getClass(), false);
        copier.copy(test, test1, null);
        System.out.println(test1.toString());
    }

    @Test
    public void cglibTest() {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(Bird.class);
        enhancer.setCallback((MethodInterceptor) (o, method, objects, methodProxy) -> {
            // 添加切面逻辑（advise），此处是在目标类代码执行之前，即为MethodBeforeAdviceInterceptor。
            System.out.println("before-------------");
            // 执行目标类add方法
            methodProxy.invokeSuper(o, objects);
            // 添加切面逻辑（advise），此处是在目标类代码执行之后，即为MethodAfterAdviceInterceptor。
            System.out.println("after--------------");
            return null;
        });
        Bird bird = (Bird) enhancer.create();
        bird.run();
    }

    /**
     * jdk动态代理实现
     *
     * @throws Exception
     */
    @Test
    public void jdkProxy() {
        Bird bird = new Bird();
        Animal animal = (Animal) Proxy.newProxyInstance(getClass().getClassLoader(), new Class[]{Animal.class}, (proxy, method, args) -> {
            System.out.println(proxy.getClass().getName());
            return method.invoke(bird, args);
        });

        String path = bird.getClass().getResource(".").getPath();
        this.saveClassFile(animal.getClass(), path);
        bird.run();
    }

    @Test
    public void serviceProxy() {
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(BaseConfig.class);
        UserService personService = (UserService) annotationConfigApplicationContext.getBean("userService");
        saveClassFile(personService.getClass(), this.getClass().getResource(".").getPath());
    }


    /**
     * 保存动态变量到本地
     *
     * @param clazz
     * @param path
     */
    private void saveClassFile(Class clazz, String path) {
        FileOutputStream fos = null;
        try {
            byte[] classFile = ProxyGenerator.generateProxyClass(clazz.getName(), clazz.getInterfaces());
            fos = new FileOutputStream(path + clazz.getName() + ".class");
            fos.write(classFile);//保存到磁盘
            fos.flush();
        } catch (Exception e) {
            e.getMessage();
        } finally {
            try {
                if (fos != null) {
                    fos.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
